package com.tvunetworks.center.user.service.impl;

import com.tvunetworks.center.common.exception.ServerException;
import com.tvunetworks.center.common.util.StreamUtil;
import com.tvunetworks.center.user.mapper.CustomizedUserDeviceGroupMapper;
import com.tvunetworks.center.user.mapper.CustomizedUserGroupMapper;
import com.tvunetworks.center.user.model.CustomizedUserDeviceGroup;
import com.tvunetworks.center.user.model.CustomizedUserGroup;
import com.tvunetworks.center.user.model.param.SetUserDeviceGroupParam;
import com.tvunetworks.center.user.model.result.ResultConstant;
import com.tvunetworks.center.user.model.vo.PeerIdGroupVo;
import com.tvunetworks.center.user.service.CustomizedUserDeviceGroupService;
import com.tvunetworks.center.user.service.CustomizedUserGroupService;
import com.tvunetworks.center.user.service.UserDeviceService;
import com.tvunetworks.center.user.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @program: tvucc-aggregator
 * @description: CustomizedUserDeviceGroupServiceImpl
 * @author lebronchen
 * @create: 2020-03-13 09:49
 **/
@Service
@Slf4j
public class CustomizedUserDeviceGroupServiceImpl extends BaseService<CustomizedUserDeviceGroup> implements CustomizedUserDeviceGroupService {

    @Autowired
    private CustomizedUserGroupService customizedUserGroupService;
    @Autowired
    private CustomizedUserGroupMapper customizedUserGroupMapper;
    @Autowired
    private UserDeviceService userDeviceService;
    @Autowired
    private CustomizedUserDeviceGroupMapper customizedUserDeviceGroupMapper;
    @Autowired
    private RedisUtil redisUtil;

    @Value("${redisKey.userDeviceGroup}")
    private String userDeviceGroupKey;

    @Override
    @Transactional
    public void setUserDeviceGroup(SetUserDeviceGroupParam param) {
        this.addDeviceGroup(param.getUserId(), param.getPeerId(), param.getUserGroupId());
    }

    @Override
    public Map<String, PeerIdGroupVo> mapPeerIdGroup(String userId, Collection<String> peerIds) {
        if (StringUtils.isEmpty(userId)) {
            return new HashMap<>(0);
        }
        if (CollectionUtils.isEmpty(peerIds)) {
            return new HashMap<>(0);
        }
        List<PeerIdGroupVo> list = customizedUserDeviceGroupMapper.listDeviceGroup(userId, peerIds);
        if (CollectionUtils.isEmpty(list)) {
            return new HashMap<>(0);
        }

        Map<String, PeerIdGroupVo> map = list.stream().filter(StreamUtil.distinctByKey(PeerIdGroupVo::getPeerId)).collect(Collectors.toMap(item -> item.getPeerId(), item -> item));
        return map;
    }

    @Override
    public void setUserDeviceGroupToCache(String userId, String peerId, String group) {
        redisUtil.set(userDeviceGroupKey + userId + peerId, group);
    }

    @Override
    public boolean isGroupExistDevice(String groupId) {
        CustomizedUserDeviceGroup record = new CustomizedUserDeviceGroup()
                .setUserGroupId(groupId);
        List<CustomizedUserDeviceGroup> list = super.selectExistList(record);
        return !CollectionUtils.isEmpty(list);
    }

    @Override
    public void filterDeviceByGroupName(String userId, String group, List<String> peerIds) {
        log.error("filterDeviceByGroupName param userId:{} peerId:{} peerIds:{}", userId, group, peerIds);
        Map<String, String> peerIdGroupMap = this.mapUserDeviceGroup(userId, peerIds);
        for (Map.Entry<String, String> entry : peerIdGroupMap.entrySet()) {
            if (!StringUtils.equals(group, entry.getValue())) {
                peerIds.remove(entry.getKey());
            }
        }
        log.error("filterDeviceByGroupName result userId:{} peerId:{} peerIds:{}", userId, group, peerIds);
    }

    @Override
    public String getUserDeviceGroupWithDefault(String userId, String peerId) {
        String group = customizedUserDeviceGroupMapper.getUserDeviceGroup(userId, peerId);
        if (StringUtils.isNotEmpty(group)) {
            return group;
        }
        String defaultGroup = customizedUserGroupService.getUserDefaultGroupName(userId);
        return defaultGroup;
    }

    @Override
    public Map<String, String> mapUserDeviceGroup(String userId, List<String> peerIds) {

        // 查询用户默认分组
        String defaultGroup = customizedUserGroupService.getUserDefaultGroupName(userId);
        // 查询所有设备的分组
        Map<String, PeerIdGroupVo> peerIdGroupVoMap = this.mapPeerIdGroup(userId, peerIds);

        // 没查到分组的设备，设置为默认分组
        Map<String, String> resultMap = new HashMap<>();
        for (String peerId : peerIds) {
            String groupName;
            PeerIdGroupVo vo = peerIdGroupVoMap.get(peerId);
            if (vo != null) {
                groupName = vo.getGroup();
            } else {
                groupName = defaultGroup;
            }
            resultMap.put(peerId, groupName);
        }
        return resultMap;
    }

    @Override
    public List<String> listGroupRids(String groupName) {
        if (StringUtils.isBlank(groupName)) {
            return new ArrayList<>();
        }
        Set<String> result = new HashSet<>();
        // 查询出所有在该分组中的 R
        List<String> inGroupRids = customizedUserDeviceGroupMapper.listGroupRids(groupName);
        if (!CollectionUtils.isEmpty(inGroupRids)) {
            result.addAll(inGroupRids);
        }
        // 查询出以该 group 为默认分组的所有 userId
        List<String> userIds = customizedUserGroupMapper.isDefaultGroupUserId(groupName);
        if (!CollectionUtils.isEmpty(userIds)) {
            // 查询出以该 group 为默认分组所有用户的 没设置分组的 R
            List<String> defaultNotInGroupRids = customizedUserDeviceGroupMapper.listUsersNotInGroupRids(userIds);
            if (!CollectionUtils.isEmpty(defaultNotInGroupRids)) {
                result.addAll(defaultNotInGroupRids);
            }
        }
        return new ArrayList<>(result);
    }

    private void addDeviceGroup(String userId, String peerId, String userGroupId) {
        CustomizedUserGroup userGroup = customizedUserGroupService.getById(userGroupId);
        // 检查分组是否存在
        if (userGroup == null) {
            ServerException.Exception(ResultConstant.CustomizedUserGroup.GROUP_NOT_EXIST);
        }
        String group = userGroup.getGroup();
        // 检查分组是否是用户的分组
        if (!StringUtils.equals(userId, userGroup.getUserId())) {
            ServerException.Exception(ResultConstant.CustomizedUserGroup.GROUP_NOT_BELONG_USER);
        }
        // 检查用户是否有该设备
        boolean userDeviceExist = userDeviceService.isUserDeviceExist(userId, peerId);
        if (!userDeviceExist) {
            ServerException.Exception(ResultConstant.UserDevice.USER_NOT_OWN_DEVICE);
        }

        // 保存 UserGroup 到 DB
        CustomizedUserDeviceGroup userDeviceGroup = this.getUserDeviceGroup(userId, peerId);
        if (userDeviceGroup != null) {
            userDeviceGroup.setUserGroupId(userGroupId);
            super.updateSelective(userDeviceGroup);
        } else {
            CustomizedUserDeviceGroup record = new CustomizedUserDeviceGroup()
                    .setUserId(userId)
                    .setPeerId(peerId)
                    .setUserGroupId(userGroupId);
            super.insert(record);
        }
        // 保存到 redis
        this.setUserDeviceGroupToCache(userId, peerId, group);
    }

    private CustomizedUserDeviceGroup getUserDeviceGroup(String userId, String peerId) {
        if (StringUtils.isEmpty(userId) || StringUtils.isEmpty(peerId)) {
            return null;
        }
        CustomizedUserDeviceGroup record = new CustomizedUserDeviceGroup()
                .setUserId(userId)
                .setPeerId(peerId);
        return super.selectExistOne(record);
    }


}
